package org.gvp.manager.service.impl;

import lombok.RequiredArgsConstructor;

import lombok.extern.log4j.Log4j2;
import org.gvp.manager.dto.AuthorityTreeData;
import org.gvp.manager.dto.AuthorityTreeUpdate;
import org.gvp.manager.dto.PathTreeData;
import org.gvp.manager.to.MapperUpdate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.gvp.common.http.Page;
import org.gvp.manager.service.SecurityRolePathService;
import org.gvp.manager.repository.SecurityRolePathRepository;
import org.gvp.manager.pojo.SecurityRolePath;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 角色请求路径关系表 服务层接口实现类
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class SecurityRolePathServiceImpl implements SecurityRolePathService {
    private final SecurityRolePathRepository securityRolePathRepository;
    @Value("${summer.manager.config.recursion-depth:5}")
    private Integer recursionDepth;

    @Override
    public int editAuthority(AuthorityTreeUpdate update) {
        log.debug("更新角色请求路径关系: {}",update);
        return this.saveRolePath(update.getId(),update.getAddNodes())
            + this.logicalRemoveAuthority(new MapperUpdate(update.getId(),update.getDeleteNodes()));
    }

    @Override
    public int saveRolePath(Integer id, List<String> addNodes) {
        if (addNodes == null || addNodes.isEmpty()){
            return 0;
        }
        AtomicInteger res = new AtomicInteger(0);
        List<Integer> ids = this.findPathIds(addNodes);
        ids.forEach(pathId -> {
           SecurityRolePath rolePath = this.findByRoleIdAndPathId(id,pathId);
           if (rolePath == null){
               rolePath = new SecurityRolePath();
               rolePath.setRoleId(id);
               rolePath.setPathId(pathId);
              res.addAndGet(this.save(rolePath));
           }else {
                res.addAndGet(this.recoverRemove(rolePath.getId()));
           }
        });
        return res.get();
    }

    @Override
    public int recoverRemove(Integer id) {
        log.debug("恢复删除角色请求路径关系: {}",id);
        return this.securityRolePathRepository.recoverCancel(id);
    }

    @Override
    public int save(SecurityRolePath pojo) {
        log.debug("添加角色请求路径关系: {}",pojo);
        return this.securityRolePathRepository.append(pojo);
    }

    public List<Integer> findPathIds(List<String> keys){
        log.debug("根据路径key列表获取路径ID列表: {}",keys);
        return this.securityRolePathRepository.searchPathIds(keys);
    }

    @Override
    public int logicalRemoveAuthority(MapperUpdate update) {
        if (update.getKeys() == null || update.getKeys().isEmpty()){
            return 0;
        }
        return this.securityRolePathRepository.logicalCancel(update);
    }

    @Override
    public AuthorityTreeData findAuthorityTreeData(Integer roleId) {
        log.debug("根据角色ID获取角色和路径关系处理权限树数据: {}",roleId);
        List<PathTreeData> renderTree = this.findRenderTree();
        List<String> expandKeys = renderTree.stream().map(e -> e.getKey()).toList();
        return new AuthorityTreeData(renderTree,findRolePathKeys(roleId),expandKeys);
    }

    /**
     * 获取渲染树
     */
    public List<PathTreeData> findRenderTree(){
        log.debug("获取路径渲染树,用于前端生成RenderTree");
        List<PathTreeData> renderTree = this.findByParentId(PAH_PARENT_ID);
        // 为渲染树生成子节点
        this.loadChildNode(renderTree,1);
        renderTree.forEach(e -> log.info("角色路径权限渲染树数据: {}",e));
        return renderTree;
    }

    /**
     * 加载渲染树的子节点
     * @param renderTree 渲染树
     * @param depth 递归深度
     */
    private void loadChildNode(List<PathTreeData> renderTree,int depth){
        if (depth > this.recursionDepth){
            log.warn("路径渲染树深度超过最大限制,已停止递归");
            return;
        }
        if (renderTree == null || renderTree.isEmpty()){
            return;
        }
        for (PathTreeData node : renderTree){
            List<PathTreeData> cn = this.findByParentId(node.getId());
            node.setChildren(cn);
            this.loadChildNode(cn, depth + 1);
        }
    }

    @Override
    public List<PathTreeData> findByParentId(Integer parentId) {
        log.debug("根据父节点ID获取路径树数据: {}",parentId);
        return this.securityRolePathRepository.searchByParentId(parentId);
    }

    @Override
    public List<String> findRolePathKeys(Integer roleId) {
        log.debug("根据角色ID获取角色路径key列表: {}",roleId);
        return this.securityRolePathRepository.searchRolePathKeys(roleId);
    }

    @Override
    public SecurityRolePath findByRoleIdAndPathId(Integer roleId, Integer pathId) {
        log.debug("根据角色ID和路径ID获取角色路径关系信息: {},{}",roleId,pathId);
        return this.securityRolePathRepository.searchByRoleIdAndPathId(roleId,pathId);
    }
}
